枚举到底是什么
- 结论,枚举只是一个对象列表,~~以前不理解这一点,走了一些弯路 ~~
- 一般人印像是枚举是不可变的,但其实不太对
- 只是枚举对象列表本身,和列表里的内容是不可变的
- 在列表里的对象的属性,只要你没有手工指定了final 其实是可变的,是可以写setter
各种被要求写枚举
必写
以下如果你不写,新入职的员工看你代码里的if(type == 0)时,会在心里默默划过几万个草泥马
- 业务各种type要写枚举
- status要写枚举
这些也要写,看公司规定
- 数据库字段
- ES索引mapping字段
使用枚举生成ES mapping
由于枚举字段是固定的,无非就是字段名,Es类型,字段描述,理论上可以像对象继承一样弄一个父类,或是抽象类来实现通用枚举
- 枚举不能继承,因为他本身继承了java.lang.Enum
- 枚举是可以实现其他接口,所以我们可以通过写一个通用接口,其他Es索引的枚举实现此接口来实现自动生成mapping
- 接口
public interface AbstractEsField {
//字段名
String getName();
//字段类型
String getEsType();
}
- 实现类
@Getter
public enum DataReportFieldEnum implements AbstractEsField {
PRIMARY_KEY("primaryKey","主键",KEYWORD,false),
;
private String name;
private String description;
private String esType;
ReceivableSplitDataReportFieldEnum(String name, String description, String esType) {
this.name = name;
this.description = description;
this.esType = esType;
}
}
- 这样我们可玩的就多了
- 比如根据枚举生成es mapping
//生成mapping工具类
class Util {
//传入ES字段枚举类生成mapping XContentBuilder
public static XContentBuilder getMappingContentBuilderByEnum(Class<? extends AbstractEsField> clazz) {
if (!clazz.isEnum()) throw new BusinessException("must be enum");
List<AbstractEsField> fieldList = Arrays.asList(clazz.getEnumConstants());
if (CollectionUtils.isEmpty(fieldList)) throw new BusinessException("enum must has values");
try {
XContentBuilder mapping = XContentFactory.jsonBuilder(new BytesStreamOutput())
.startObject().field("dynamic", "false")
.startObject("properties");
for (AbstractEsField item : fieldList) {
if (!Objects.equals(item.getEsType(), EsConstants.NESTED)) {
//有父字段的字段走嵌套字段处理
if (StringUtils.isNotBlank(item.getParentName())) continue;
assembMapping(mapping, item);
} else {
//嵌套字段单独处理
List<AbstractEsField> childFieldList = fieldList.stream().filter(x -> Objects.equals(x.getParentName(), item.getName())).collect(Collectors.toList());
//只支持单层嵌套
if (childFieldList.stream().anyMatch(x -> Objects.equals(x.getEsType(), EsConstants.NESTED))) {
throw new BusinessException("only support one layer nested");
}
//没有子字段忽略嵌套字段
if (CollectionUtils.isEmpty(childFieldList)) continue;
mapping.startObject(item.getName()).field(EsConstants.TYPE, item.getEsType());
mapping.startObject("properties");
for (AbstractEsField chiledField : childFieldList) {
assembMapping(mapping, chiledField);
}
mapping.endObject().endObject();
}
}
mapping.endObject().endObject();
return mapping;
} catch (IOException e) {
throw new BusinessException("io error",e);
}
}
//传入ES字段枚举类生成mapping json String
public static String getMappingJsonStringByEnum(Class<? extends AbstractEsField> clazz) {
XContentBuilder mappingContentBuilder = getMappingContentBuilderByEnum(clazz);
mappingContentBuilder.close();
return ((BytesStream) mappingContentBuilder.getOutputStream()).bytes().utf8ToString();
}
//单个非嵌套字段mapping装配
private static void assembMapping(XContentBuilder mapping, AbstractEsField esField) throws IOException {
mapping.startObject(esField.getName()).field(EsConstants.TYPE, esField.getEsType()).field("store", "true");
//数值类默认值处理
if (EsConstants.NUMBER_TYPES.contains(esField.getEsType())) {
mapping.field("null_value", EsConstants.DEFAULT_NUMBER_VALUE);
}
//scaled_float 默认缩放因子100
if (Objects.equals(esField.getEsType(), EsConstants.SCALED_FLOAT)) {
mapping.field("scaling_factor", EsConstants.DEFAULT_SCALED_FLOAT_FACTOR);
}
//date 默认format处理
if (Objects.equals(esField.getEsType(), EsConstants.DATE)) {
mapping.field("format", EsConstants.DEFAULT_DATE_FORMAT);
}
mapping.endObject();
}
public static void main(String[] args) {
System.out.println(Util.getMappingJsonStringByEnum(DataReportFieldEnum.class));
}
}
-
为了统一我们可以把这个类放到AbstractEsField里
-
end ,枚举生成数据库相关代码也一样的思路,生成的代码,总是会比自己写的要好用,不会出错